<?php
/**
 * Description of canvas
 *
 * @author jguan
 */
class AniCavas{
    /**
     * @var array array of Animate class
     */
    private $animates;
    /**
     * @var int the image delay for animation
     */
    private $delay = 50;
    /**
     * @var int the option value the ffmpeg
     */
    private $fps = 2;
    /**
     * @var stdClass the logo for company
     */
    private $logo;
    /**
     * @var array  array of annotations
     */
    private $annotations;
    /**
     * @var array  array of images
     */
    private $images;
    /**
     * @var int the canvas width
     */
    private $width;
    /**
     * @var int the canvas height
     */
    private $height;
    /**
     * @var Imagick the imagick object for anicanvas
     */
    private $im;

    function __construct($width, $height){
        $this->width = $width;
        $this->height = $height;
    }
    /**
     * adding an animate to canvas
     * @param <Animation> $animation
     * @param <int> $x
     * @param <int> $y
     * @param <int> $width
     * @param <int> $height
     */
    function addAnimation($animation, $x, $y, $width="", $height=""){
        $newanimation->animation = $animation;
        $newanimation->x = $x;
        $newanimation->y = $y;
        $newanimation->width = $width;
        $newanimation->height = $height;
        $this->animates[] = $newanimation;
    }
    /**
     * adding an annotation to canvas
     * @param <string> $text
     * @param <int> $x
     * @param <int> $y
     */
    function addAnnotation($text, $x, $y){
        $newAnnotate = new stdClass();
        $newAnnotate->text = $text;
        $newAnnotate->x = $x;
        $newAnnotate->y = $y;
        $this->annotations[] = $newAnnotate;
    }
    /**
     * adding an image to canvas
     * @param <type> $filesrc
     * @param <type> $x
     * @param <type> $y 
     */
    function addImage($filesrc, $x, $y){
        $newim->im = new Imagick($filesrc);
        $newim->x = $x;
        $newim->y = $y;
        $this->images[] = $newim;
    }
    function prepareBackground(){
        if(!$this->im){
            $this->im = new Imagick();
            $this->im->newImage($this->width, $this->height, new ImagickPixel("white"), "png");
            if(count($this->annotations)){
                foreach($this->annotations as $annotate){
                    $this->im->annotateImage(new ImagickDraw(), $annotate->x, $annotate->y, $angle = 0, $annotate->text);
                }
            }
            //        //adding image;
            if(count($this->images)){
                foreach($this->images as $image){
                    $this->im->compositeImage($image->im, IMAGICK::COMPOSITE_DISSOLVE, $image->x, $image->y);
                }
            }
        }
        return $this->im->clone();
    }
    /**
     * set the company logo
     * @param <type> $filesrc     
     * @param <type> $x
     * @param <type> $y 
     */
    function setLogo($filesrc, $x, $y){
        $this->addImage($filesrc, $x, $y);
        $this->logo = $this->images[count($this->images) - 1];
    }
    /**
     * get a special index of one frame
     * @param int $idx
     * @param int $width
     * @param int $height
     * @return Imagick a single frame
     */
    function getFrame($idx, $width = "", $height = ""){
        $frame = $this->prepareBackground();
        //adding animation area;
        foreach($this->animates as $animation){
            $aniFrame = $animation->animation->getFrame($idx);
            //$aniFrame->writeImage("middle_test_before.png");
            if($animation->width){
                $aniFrame->resizeImage($animation->width, $animation->height, $filter = IMAGICK::FILTER_UNDEFINED, $blur = 1);
            }
            //$aniFrame->writeImage("middle_test.png");
            if($aniFrame){
                $frame->compositeImage($aniFrame, IMAGICK::COMPOSITE_DISSOLVE, $animation->x, $animation->y);
            }
            //$frame->writeImage("canvas_middle_test.png");
        }
        if($width){
            $frame->resizeImage($width, $height, $filter = IMAGICK::FILTER_UNDEFINED, $blur = 1);
        }
        return $frame;
    }
    /**
     * save one frame to a image file
     * @param int $idx the special index frame
     * @param string $filename the output file name
     */
    function saveFrame($idx, $filename){
        $frame = $this->getFrame($idx);
        $filename = $filename ? $filename : "ani_cavas_frame_ouput.png";
        $frame->writeImage($filename);
    }
    /**
     * do exactly that generate animation canvas
     * @param string $filename the ouput image name with path
     * @param int $width the output image width
     * @param int $height the output image height
     * @return boolean
     */
    function make($filename = "", $width = "", $height = ""){
        $count = $this->getMaxCount();
        $aniGifCanvas = new Imagick();

        for($idx = 0; $idx < $count; $idx++){//do frame adding circlely
            $frame = $this->getFrame($idx, $width, $height);
            $aniGifCanvas->addImage($frame);
            $aniGifCanvas->setImageDelay($this->delay);
        }
        $filename = $filename ? $filename : "ani_canvas_output.gif";
        $aniGifCanvas->writeImages($filename, true);
        if(file_exists($filename)){
            return true;
        }else{
            return false;
        }
    }
    /**
     * get the max count of animation items
     * @return int the max count of animation items
     */
    function getMaxCount(){
        if(!$this->maxCount){
            $tmpCount = 0;
            foreach($this->animates as $animation){
                $rastersCount = $animation->animation->getRastersCount();
                if($rastersCount > $tmpCount){
                    $tmpCount = $rastersCount;
                }
            }
            $this->maxCount = $tmpCount;
        }

        return $this->maxCount;
    }
    /**
     * set the animation frame delay value
     * @param <type> $delay its unit is micro-second
     */
    function setDelay($delay){
        $this->delay = $delay;
        $this->fps = round(100 / $this->delay);
    }
    /**
     * make frames to sequerence wmv file
     * @param string $ffmpeg the ffmpeg's full path
     * @param string $output output file name
     */
    function makeWmv($ffmpeg = "", $output = ""){
        //generate tmp images

        $count = $this->getMaxCount();
        echo $count."\n";
        for($idx = 0; $idx < $count; $idx++){
            $tmp = substr(10001 + $idx, 1);
            $filename = "imagetmp/tmp_{$tmp}.jpg";
            echo $filename.".\n";
            $this->saveFrame($idx, $filename);
        }

        $input = dirname(__FILE__)."/imagetmp/tmp_%4d.jpg";
        if(!$output )$output = $output ? $output : "anicanvas_output.wmv";
        $cmd = "ffmpeg -r $this->fps -f image2 -i $input $output";
        echo $cmd."\n";
        @exec($cmd);
    }
}
?>
